class WebGLPlayground {
    constructor() {
        this.canvas = document.getElementById('renderCanvas');
        this.gl = this.canvas.getContext('webgl2');
        this.program = null;

        // 历史记录相关
        this.history = {
            vertex: [],
            fragment: [],
            currentIndex: -1
        };
        
        // 保存初始状态
        this.initialVertexShader = document.getElementById('vertexShader').value;
        this.initialFragmentShader = document.getElementById('fragmentShader').value;

        // 初始化WebGL
        if (!this.gl) {
            this.showError('浏览器不支持WebGL 2');
            return;
        }

        // 绑定事件
        document.getElementById('compileBtn').addEventListener('click', () => this.compile());
        document.getElementById('undoBtn').addEventListener('click', () => this.undo());
        document.getElementById('redoBtn').addEventListener('click', () => this.redo());

        // 监听文本框变化
        document.getElementById('vertexShader').addEventListener('input', () => this.onShaderChange());
        document.getElementById('fragmentShader').addEventListener('input', () => this.onShaderChange());

        // 初始渲染
        this.saveState(); // 保存初始状态
        this.updateButtons();
        this.compile();
    }

    onShaderChange() {
        // 当着色器代码发生变化时，清除当前历史记录中当前位置之后的所有记录
        if (this.history.currentIndex < this.history.vertex.length - 1) {
            this.history.vertex = this.history.vertex.slice(0, this.history.currentIndex + 1);
            this.history.fragment = this.history.fragment.slice(0, this.history.currentIndex + 1);
        }
        
        this.saveState();
        this.updateButtons();
    }

    saveState() {
        const vertexShader = document.getElementById('vertexShader').value;
        const fragmentShader = document.getElementById('fragmentShader').value;
        
        this.history.vertex.push(vertexShader);
        this.history.fragment.push(fragmentShader);
        this.history.currentIndex = this.history.vertex.length - 1;
    }

    undo() {
        if (this.canUndo()) {
            this.history.currentIndex--;
            this.restoreState();
            this.updateButtons();
            this.compile();
        }
    }

    redo() {
        if (this.canRedo()) {
            this.history.currentIndex++;
            this.restoreState();
            this.updateButtons();
            this.compile();
        }
    }

    canUndo() {
        return this.history.currentIndex > 0;
    }

    canRedo() {
        return this.history.currentIndex < this.history.vertex.length - 1;
    }

    restoreState() {
        const vertexShader = this.history.vertex[this.history.currentIndex];
        const fragmentShader = this.history.fragment[this.history.currentIndex];
        
        document.getElementById('vertexShader').value = vertexShader;
        document.getElementById('fragmentShader').value = fragmentShader;
    }

    updateButtons() {
        document.getElementById('undoBtn').disabled = !this.canUndo();
        document.getElementById('redoBtn').disabled = !this.canRedo();
    }

    compile() {
        const vsSource = document.getElementById('vertexShader').value;
        const fsSource = document.getElementById('fragmentShader').value;

        // 清理旧程序
        if (this.program) {
            this.gl.deleteProgram(this.program);
        }

        try {
            this.program = this.createProgram(vsSource, fsSource);
            this.render();
            this.showError(''); // 清空错误
        } catch (error) {
            this.showError(error.message);
            // 添加弹窗提示
            alert('着色器运行错误:\n' + error.message);
        }
    }

    createProgram(vsSource, fsSource) {
        const vertexShader = this.compileShader(this.gl.VERTEX_SHADER, vsSource);
        const fragmentShader = this.compileShader(this.gl.FRAGMENT_SHADER, fsSource);

        const program = this.gl.createProgram();
        this.gl.attachShader(program, vertexShader);
        this.gl.attachShader(program, fragmentShader);
        this.gl.linkProgram(program);

        if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {
            throw new Error(this.gl.getProgramInfoLog(program));
        }

        return program;
    }

    compileShader(type, source) {
        const shader = this.gl.createShader(type);
        this.gl.shaderSource(shader, source);
        this.gl.compileShader(shader);

        if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
            const error = this.gl.getShaderInfoLog(shader);
            this.gl.deleteShader(shader);
            throw new Error(`着色器编译错误:\n${error}`);
        }

        return shader;
    }

    render() {
        // 设置画布尺寸
        const container = this.canvas.parentElement;
        this.canvas.width = container.clientWidth;
        this.canvas.height = container.clientHeight;
        this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);

        // 创建全屏三角形
        const positions = new Float32Array([
            -1, -1, 0,
            3, -1, 0,
            -1, 3, 0
        ]);

        const buffer = this.gl.createBuffer();
        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer);
        this.gl.bufferData(this.gl.ARRAY_BUFFER, positions, this.gl.STATIC_DRAW);

        // 渲染
        this.gl.useProgram(this.program);
        const positionLoc = this.gl.getAttribLocation(this.program, 'position');
        this.gl.enableVertexAttribArray(positionLoc);
        this.gl.vertexAttribPointer(positionLoc, 3, this.gl.FLOAT, false, 0, 0);

        this.gl.drawArrays(this.gl.TRIANGLES, 0, 3);
    }

    showError(message) {
        document.getElementById('errorOutput').textContent = message;
    }
}

// 初始化应用
new WebGLPlayground();